using System;
using System.Collections.Generic;
using PowerSearch.Core;
using System.Xml.Linq;
using System.Linq;

namespace PowerSearch.AppServices.Parser.Provider
{
	public class EbayParser : BaseFeedParser
	{
		private enum ResponseStatus
		{
			Success,
			Warning,
			Failure,
			PartialFailure
		}
		public override string BaseUrl
		{
			get
			{
				return
					"http://svcs.ebay.com/services/search/FindingService/v1?OPERATION-NAME=findItemsByKeywords&SERVICE-VERSION=1.0.0&SECURITY-APPNAME=DantaCor-fab6-41f0-832e-effdf0c3b85d&RESPONSE-DATA-FORMAT=XML&REST-PAYLOAD&keywords={0}&paginationInput.entriesPerPage=10";
			}
		}

		protected internal override IList<Feed> ParseFeed(string responseData)
		{
			var feedList = new List<Feed>();
			var xmlDoc = XDocument.Parse(responseData);
			if (xmlDoc.Root != null)
			{
				var ns = xmlDoc.Root.GetDefaultNamespace();

				// Check if response return a errror message because request is invalid
				if (xmlDoc.Root.Name.LocalName.Equals("errorMessage", StringComparison.OrdinalIgnoreCase))
				{
					ParseAndLogError(xmlDoc.Root);
				}
				else
				{
					//If response response result (Success, Waring, Failure or PartialFailure)
					//Both Success and Warning Indicate a Successful Request
					//result status is element <ack>[Success]</ack>
					var resultStatus = xmlDoc.Root.Element(ns + "ack");
					if (resultStatus != null && (resultStatus.Value.Equals(ResponseStatus.Success.ToString(), StringComparison.OrdinalIgnoreCase) ||
					                             resultStatus.Value.Equals(ResponseStatus.Warning.ToString(), StringComparison.OrdinalIgnoreCase)))
					{
						xmlDoc.Root.Descendants(ns + "item").ToList().ForEach(item => feedList.Add(CreateFeedItem(item, ns)));
					}
					else
					{
						ParseAndLogError(xmlDoc.Root);
					}

				}

			}
			return feedList;
		}

		#region Private methods

		private Feed CreateFeedItem(XElement itemElement, XNamespace ns)
		{
			var feed = new EbayFeed();

			var titleElement = itemElement.Element(ns + "title");
			feed.Title = titleElement != null ? titleElement.Value : string.Empty;
			var sellingStatusElement = itemElement.Element(ns + "sellingStatus");
			if (sellingStatusElement != null)
			{
				var bidCountElement = sellingStatusElement.Element(ns + "bidCount");
				feed.Bids = bidCountElement != null ? FormatBids(bidCountElement.Value) : "Fixed Price";
				var timeLeftElement = sellingStatusElement.Element(ns + "timeLeft");
				if (timeLeftElement != null)
					feed.TimeLeft = FormatTimeLeft(timeLeftElement.Value);
				var currentPriceElement = sellingStatusElement.Element(ns + "currentPrice");
				if (currentPriceElement != null)
					feed.Price = currentPriceElement.Value;
			}
			feed.Description = FormatDescription(feed.Bids, feed.TimeLeft, feed.Price);
			var galleryUrlElement = itemElement.Element(ns + "galleryURL");
			feed.DisplayUrl =galleryUrlElement!= null? galleryUrlElement.Value: string.Empty; 
			var viewItemUrlElement = itemElement.Element(ns + "viewItemURL");
			feed.ClickUrl = viewItemUrlElement != null ? viewItemUrlElement.Value : string.Empty;

			return feed;
		}

		private string FormatDescription(string bidCount, string timeLeft, string currentPrice)
		{
			return string.Format("Total bids: {0}. Time Left: {1}. Price: {2}", bidCount, timeLeft, currentPrice);
		}

		private string FormatBids(string format)
		{
			return format + " bids";
		}

		private string FormatTimeLeft(string target)
		{
			try
			{
				var timeSpan = System.Xml.XmlConvert.ToTimeSpan(target);
				return string.Format("{0:%d} days {0:%h} hours {0:%m} minutes", timeSpan);
			}
			catch (Exception ex)
			{
				//Add log
				return string.Empty;
			}
		}

		private void ParseAndLogError(XElement errorElement)
		{
			//LogWriter.Write(LogLevel.Debug, "Ebay response failure. \n" + errorElement.ToString());
		}

		#endregion
	}

	[Serializable]
	public class EbayFeed : Feed
	{
		public string Bids
		{
			get;
			set;
		}

		public string Price
		{
			get;
			set;
		}

		public string TimeLeft
		{
			get;
			set;
		}
	}
}

